package com.csaba.connector.citi;

import java.io.StringReader;
import java.text.SimpleDateFormat;
import java.util.logging.Logger;

import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;

import com.csaba.connector.ServiceException;
import com.csaba.connector.citi.model.CitiBank;
import com.csaba.connector.citi.model.CitiSession;
import com.csaba.connector.citi.parser.AccountHistoryParser;
import com.csaba.connector.citi.parser.CitiCodes;
import com.csaba.connector.citi.parser.CitiParser;
import com.csaba.connector.model.Session;
import com.csaba.connector.service.AbstractAccountHistoryService;
import com.csaba.util.IntervalDates;
import com.csaba.util.LoggerHelper;

public class CitiAccountHistoryService extends AbstractAccountHistoryService
{

	private final static Logger logger = LoggerHelper.getDefaultLogger();

	@Override
	public void execute( final Session session ) throws ServiceException
	{
		if ( !( session instanceof CitiSession ) )
			throw new ServiceException("Incompatible session " + CitiBank.class + " != " + session.getClass().getName());

		if ( account == null || !CitiBank.getInstance().equals(account.getBank()) )
			throw new ServiceException("Service is not initialized yet correctly.");

		if ( from == null || to == null )
			throw new ServiceException("Please enter both the Date from and the Date to.");

		//time range is limited to 3 month (90 days)... 
		final IntervalDates iDates = new IntervalDates(CitiCodes.HISTORY_TIME_LIMIT, false);

		if ( !( iDates.isInInterval(from) && iDates.isInInterval(to) ) )
		{
			throw new ServiceException("Account history is available only for the last " + iDates.getInterval()
					+ " days!\nPlease enter a date from " + iDates.getFrom() + " to " + iDates.getTo() + ".");
		}

		final CitiSession citiSession = (CitiSession) session;

		try
		{
			// FIXME reload
			// All functions of account information menu use the same URL to post the request
			// These functions are differentiated with TK value of SELCHOICE parameter -> CH1:TK1 or CH1:TK2 or CH1:TK3
			final String accountServiceURL = (String) citiSession.getRemoteProperty(CitiCodes.CACHE_ACCOUNTSERVICE_URL);

			if ( accountServiceURL.isEmpty() )
				throw new ServiceException("Service is not initialized correctly.");

			// Select "Download Account Activity" function in account information menu
			// This function creates first a dummy page 
			// Citi page title:  "DAA 000 - Flashing dummy screen"  
			// POSTDATA=SELCHOICE=CH1:TK3&TAGTYPE=
			final NameValuePair[] nvpInitDAA = new NameValuePair[] { //
			new BasicNameValuePair("SELCHOICE", "CH1:TK3"), //
					new BasicNameValuePair("TAGTYPE", "") };
			final String resultInitDAA = citiSession.doPost(accountServiceURL, nvpInitDAA);
			citiSession.debugFile("resultInitDAA", resultInitDAA);
			final String parameterPageDAA_URL = CitiParser.parseNextURL(new StringReader(resultInitDAA));

			if ( parameterPageDAA_URL.isEmpty() )
				throw new IllegalStateException(resultInitDAA);
			logger.fine("Succesful creation of Download Account Activity page");

			//create the parameter page for Download Account Activity
			// Citi page title: Download Account Activity
			final NameValuePair[] nvpDummy = new NameValuePair[] { //
			new BasicNameValuePair("dummy", "") };
			final String resultParameterPageDAA = citiSession.doPost(parameterPageDAA_URL, nvpDummy);
			citiSession.debugFile("resultParameterPageDAA", resultParameterPageDAA);
			final String downloadFileURL = AccountHistoryParser.parseFileDownloadURL(new StringReader(
					resultParameterPageDAA));

			if ( downloadFileURL.isEmpty() )
				throw new IllegalStateException(resultParameterPageDAA);
			logger.fine("Succesfuly initialized query parameters");

			//Select "Download file" link in order to start CVS history file download
			//Citi page title:  "DAA 200 - I'm working on..." 
			//POSTDATA=SelFormat=0&SaveActivity=1&sFromDate=01.12.2008&sToDate=31.12.2008&For=1&sAcctsSelected=0&sCookieDates=07300820081224&sFileFormatOption=3&sPreselectSinceLastDld=N&sPreselectAllAccts=N&DoWhat=D&sPreselectDateRange=N&IExpSP2=undefined
			final SimpleDateFormat dateFormat = CitiCodes.dateFormat.get();
			final NameValuePair[] nvpFileDownload = new NameValuePair[] {
					new BasicNameValuePair("SelFormat", "0"),
					new BasicNameValuePair("SaveActivity", "1"), //(1) down load with date interval (0) down load from date of last down load 
					new BasicNameValuePair("sFromDate", dateFormat.format(from)),
					new BasicNameValuePair("sToDate", dateFormat.format(to)), new BasicNameValuePair("For", "1"), //down load with selected account 
					new BasicNameValuePair("sAcctsSelected", "0"), //selected account - index of account array (?)
					new BasicNameValuePair("sCookieDates", ""), // sToDate of last down load; value is read from "DATES" cookie; please see detailed description after this class 
					new BasicNameValuePair("sFileFormatOption", "3"), //CSV: sFileFormatOption.value = document.fbot.SelFormat.selectedIndex
					new BasicNameValuePair("sPreselectSinceLastDld", "N"), //
					new BasicNameValuePair("sPreselectAllAccts", "N"), new BasicNameValuePair("DoWhat", "D"), //DoWhat.value = "D"
					new BasicNameValuePair("sPreselectDateRange", "N"), //
					new BasicNameValuePair("IExpSP2", "undefined") //Internet Explorer SP2
			};
			final String resultWorkingOnDAAFile = citiSession.doPost(downloadFileURL, nvpFileDownload);
			citiSession.debugFile("resultWorkingOnDAAFile", resultWorkingOnDAAFile);
			final String downloadProgressURL = CitiParser.parseNextURL(new StringReader(resultWorkingOnDAAFile));

			if ( downloadProgressURL.isEmpty() )
				throw new IllegalStateException(resultWorkingOnDAAFile);
			logger.fine("Succesfuly created \"DAA 200 - I'm working on...\" page");

			//Next dummy page - Download progress
			//Citi page title: "DAA 210 - Download progress - no more account to download"
			final String resultDownloadProgressDAAFile = citiSession.doPost(downloadProgressURL, nvpDummy);
			citiSession.debugFile("resultDownloadProgressDAAFile", resultDownloadProgressDAAFile);
			final String downloadURL = CitiParser.parseNextURL(new StringReader(resultDownloadProgressDAAFile));

			if ( downloadURL.isEmpty() )
				throw new IllegalStateException(resultDownloadProgressDAAFile);
			logger.fine("Succesfuly created \"DAA 210 - Download progress...\" page");

			//Download CVS file with Account Activity content 
			//POSTDATA=sCookieDates=07300820081230&sDA6CookieDates=&State=Refresh
			final NameValuePair[] nvpCVSDownload = new NameValuePair[] { //
			new BasicNameValuePair("sCookieDates", ""), //it should be the sToDate of this down load; please see detailed description after this class 
					new BasicNameValuePair("sDA6CookieDates", ""), //
					new BasicNameValuePair("State", "Refresh") };
			final String resultDAAFile = citiSession.doPost(downloadURL, nvpCVSDownload);
			citiSession.debugFile("resultDAAFile", resultDAAFile);
			//FIXME: Check content type: Content-Type=DAA/CSV; name=MC_008.CSV

			// parse account history
			historyItems = AccountHistoryParser.parseAccountHistoryList(new StringReader(resultDAAFile), account);

			if ( historyItems.length < 1 )
				throw new IllegalStateException(resultDAAFile);

			logger.fine("Succesful query of account history");

		}
		catch ( final IllegalStateException illegalStateException )
		{
			logger.fine("Error during processing account history ... Parsing messaging.");
			String message = null;
			try
			{
				message = CitiParser.parseErrorMsg(new StringReader(illegalStateException.getMessage()));
			}
			catch ( final Exception ex )
			{
				throw new ServiceException("Error during processing account history (error message).", ex);
			}

			throw new ServiceException("Error during processing account history.", message);
		}
		catch ( final Exception ex )
		{
			throw new ServiceException("Unable to download a valid account history.", ex);
		}
	}

}

/*
 * Description of sCookieDates parameter:
 * ----------------------------------------
 * sCookieDates.value = GetCookie ("DATES")
 * DATES cookie: domain = ".cbol.citibank.hu"
 * value example: 07300820081230 where the last 6 digits are YYMMDD of last down load of account history
 * cookiePath = "/HomeBankingSecure/DAA"
 * set expires:
 * final Date expdt = new Date();
 * final long l = (long) 2 * 365 * 24 * 60 * 60 * 1000;
 * expdt.setTime(expdt.getTime() + l);
 * set domain:
 * String dom = "https://home1hu.cbol.citibank.hu";
 * dom = dom.substring(dom.indexOf('.'));
 * set cookie:
 * function SetCookie (name,value,expires,path,domain,secure) 
 * {
 * document.cookie = name + "=" + EscCookie (value) +
 * ((expires) ? "; expires=" + expires.toGMTString() : "") +
 * ((path) ? "; path=" + path : "") +
 * ((domain) ? "; domain=" + domain : "") +
 * ((secure) ? "; secure" : "");
 * }
 *
 * function EscCookie(ival) {
 * var oval = ""
 * var ch
 * if (ival == null)
 * return null
 * for (var i=0;i<ival.length;i++) {
 * ch = ival.charAt(i)
 * if (ch == ' ')
 * oval += "%20"
 * else if (ch == ';')
 * oval += "%3B"
 * else if (ch == ',')
 * oval += "%2C"
 * else if (ch == '\t')
 * oval += "%0B"
 * else if (ch == '\r')
 * oval += "%0D"
 * else if (ch == '\n')
 * oval += "%0A"
 * else if (ch == '%')
 * oval += "%25"
 * else
 * oval += ch
 * }
 * return oval
 * }
 * 
 */
